package com.platform.comm.web;

import com.google.common.collect.Maps;
import com.platform.comm.web.results.DataJsonResult;
import com.platform.comm.web.results.JsonResult;
import com.platform.comm.web.results.PageListJsonResult;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;

import java.io.Serializable;
import java.util.Map;
import java.util.Optional;
import java.util.function.*;

/**
 * Description: Controller公共方法(用于消除代码重复)
 *
 * @author libin
 * Created on 2019/4/23
 **/
public class BaseController {

    public <T> JsonResult createOrModify(Consumer<T> consumer, T t) {
        JsonResult result = JsonResult.of();
        consumer.accept(t);
        return result.succeed();
    }

    public <T, R> DataJsonResult<R> createOrModifyWithResult(Function<T, R> function, T t) {
        return DataJsonResult.succeed(function.apply(t));
    }

    public <T> JsonResult removeOrOtherByIds(Consumer<T> consumer, T t) {
        JsonResult result = JsonResult.of();
        consumer.accept(t);
        return result.succeed();
    }

    public <T, U> JsonResult change(BiConsumer<T, U> consumer, T t, U u) {
        JsonResult result = JsonResult.of();
        consumer.accept(t, u);
        return result.succeed();
    }


    public <E, T, U, R extends Page<E>> PageListJsonResult<E> queryByPaging(BiFunction<T, U, R> biFunction, T t, U u) {
        return new PageListJsonResult<>(biFunction.apply(t, u));
    }

    public <E, T, U, V, R extends Page<E>> PageListJsonResult<E> queryByPaging(ThirdFunction<T, U, V, R> function, T t, U u, V v) {
        return new PageListJsonResult<>(function.apply(t, u, v));
    }

    public <T, R> DataJsonResult<R> query(Function<T, R> function, T t) {
        return DataJsonResult.succeed(function.apply(t));
    }

    public <T> DataJsonResult<T> query(Supplier<T> supplier) {
        return DataJsonResult.succeed(supplier.get());
    }

    public <T, U, R> DataJsonResult<R> query(BiFunction<T, U, R> biFunction, T t, U u) {
        return DataJsonResult.succeed(biFunction.apply(t, u));
    }

    public <T, U, V, R> DataJsonResult<R> query(ThirdFunction<T, U, V, R> biFunction, T t, U u, V v) {
        return DataJsonResult.succeed(biFunction.apply(t, u, v));
    }

    @FunctionalInterface
    protected interface ThirdFunction<T, U, V, R> {
        /**
         * Applies this function to the given arguments.
         *
         * @param t the first function argument
         * @param u the second function argument
         * @param v the third function argument
         * @return the function result
         */
        R apply(T t, U u, V v);

    }

    public <T, R> JsonResult upload(Function<T, R> function, T t) {
        JsonResult jsonResult = JsonResult.of();
        function.apply(t);
        return jsonResult.succeed();
    }

    public <T, U> JsonResult modify(BiConsumer<T, U> biConsumer, T t, U u) {
        JsonResult result = JsonResult.of();
        biConsumer.accept(t, u);
        return result.succeed();
    }

    public static <E extends Enum<E>, R> Map<String, R> enum2Map(Class<E> enumClass, Function<E, R> valueMapper) {
        return enum2Map(enumClass, E::name, valueMapper);
    }

    public static <E extends Enum<E>, K extends Serializable, R> Map<K, R> enum2Map(Class<E> enumClass, Function<E, K> keyMapper, Function<E, R> valueMapper) {
        Map<K, R> map = Maps.newLinkedHashMap();
        for (E e : enumClass.getEnumConstants()) {
            map.put(keyMapper.apply(e), valueMapper.apply(e));
        }
        return map;
    }

    public static Pageable getPageable(Map<?, ?> map) {
        int page = Optional.ofNullable(map.get("page")).map(item -> Integer.parseInt(item.toString())).orElse(1);
        int size = Optional.ofNullable(map.get("size")).map(item -> Integer.parseInt(item.toString())).orElse(10);
        return PageRequest.of(page - 1, size);
    }
}
